﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using anks.Lib.Config;
using anks.Lib.Logging;
using anks.Components;

namespace anks.Core
{
    public class ServiceProvider
    {
        public ServiceProvider()
        {            
        }

        ~ServiceProvider()
        {
            Shutdown();
            FinalizeCore();
        }

        #region logging
        protected virtual void AssignLoggingListeners(Logging log)
        {
        }
        protected virtual Logging CreateLogging()
        {
            Logging log = new Logging();
            AssignLoggingListeners(log);
            return log;
        }
        private Logging _logging;
        public Logging logging { get { return _logging; } } 
        #endregion

        #region config
        protected virtual CustomConfigReader GetConfigReader()
        {
            return new ConfigReaderIni();
        }
        protected virtual string GetConfigSource()
        {
            return "";
        }
        protected virtual Config CreateConfig()
        {
            return GetConfigReader().Read(GetConfigSource());
        }
        private Config _config;
        public Config config { get { return _config; } } 
        #endregion

        #region component registry
        protected virtual ComponentRegistry CreateComponentRegistry()
        {
            return new ComponentRegistry(config);
        }
        private ComponentRegistry _componentRegistry;
        public ComponentRegistry componentRegistry { get { return _componentRegistry; } } 
        #endregion

        #region initialization
        protected virtual void DoInitializeCore()
        {
            _config = CreateConfig();
            _logging = CreateLogging();
            _componentRegistry = CreateComponentRegistry();
        }

        public void InitializeCore()
        {
            if (!isInitialized)
            {
                DoInitializeCore();
                logging.info.Log("initialize core");
                _isInitialized = true;
            }
        }

        protected virtual void DoFinalizeCore()
        {
            _componentRegistry = null;
            _logging = null;
            _config = null;
        }

        public void FinalizeCore()
        {
            if (isInitialized)
            {
                logging.info.Log("finalize core");
                DoFinalizeCore();
                _isInitialized = false;
            }
        }

        private bool _isInitialized;
        public bool isInitialized { get { return _isInitialized; } } 
        #endregion

        #region startup/shutdown
        protected virtual void DoStartup()
        {
            foreach (var item in componentRegistry.Implementations)
            {
                logging.info.Log("start up " + item.Key);
                item.Value.StartUp();
            }
        }

        public void Startup()
        {
            if (!isStarted)
            {
                logging.info.Log("start up core");
                DoStartup();
                _isStarted = true;
            }
        }

        protected virtual void DoShutdown()
        {
            foreach (var item in componentRegistry.Implementations.Reverse())
            {
                logging.info.Log("shut down " + item.Key);
                item.Value.ShutDown();
            }
        }

        public void Shutdown()
        {
            if (isStarted)
            {
                logging.info.Log("shut down core");
                DoShutdown();
                _isStarted = false;
            }
        }

        public void Restart()
        {
            Shutdown();
            Startup();
        }

        private bool _isStarted;
        public bool isStarted
        {
            get
            {
                return _isStarted;
            }
            set
            {
                if (value)
                {
                    Startup();
                }
                else
                {
                    Shutdown();
                }
            }
        } 
        #endregion

    }
}
